// 基于element-plus的视图组件
window.joEl = {};

// joEl组件
(function () {
    joEl.component = joEl.install = function (app) {
        // 注册组件
        for (var k in joEl.COMPONENT_MAP) {
            app.component(k, joEl.COMPONENT_MAP[k]);
        }
    };
    /**
     * 获取ref对象
     * @param _this vue实例,直接传this
     * @param refName ref名字
     * @returns {*|null}
     */
    joEl.getRef = function (_this, refName) {
        // 先获取子ref
        var ref = _this.$refs[refName];
        // ref无效则从根节点开始找
        if (!ref) {
            ref = joEl.findRefRecursion(_this.$root, refName);
        }
        return ref;
    };
    /**
     * 递归查找ref
     * @param refIns ref实例
     * @param refName 要查找的ref名字
     * @returns {null|*}
     */
    joEl.findRefRecursion = function (refIns, refName) {
        if (!refIns || !refIns.$refs) {
            return null;
        }
        var ref = refIns.$refs[refName];
        if (!ref) {
            for (var k in refIns.$refs) {
                ref = joEl.findRefRecursion(refIns.$refs[k], refName);
                if (ref) {
                    break;
                }
            }
        }
        return ref;
    };
    // el表单校验规则
    joEl.rules = {
        required: function (msg, trigger) {
            return {required: true, message: msg || '必填项', trigger: trigger || 'blur'};
        },
        range: function (msg, trigger, min, max) {
            return {min: min, max: max, message: msg || '超出范围', trigger: trigger || 'blur'};
        },
        length: function (msg, trigger, len) {
            return {
                validator: function (rule, value, callback) {
                    if (value && value.length > len) {
                        callback(new Error(msg || ('长度超出限制:' + len)));
                    } else {
                        callback();
                    }
                }
                , trigger: trigger || 'blur'
            };
        },
        mail: function (msg, trigger) {
            return {
                validator: function (rule, value, callback) {
                    if (value) {
                        if (!jo.Const.REG_MAIL.test(value)) {
                            callback(new Error(msg || '邮箱格式错误'));
                            return;
                        }
                    }
                    callback();
                }
                , trigger: trigger || 'blur'
            };
        },
        phone: function (msg, trigger) {
            return {
                validator: function (rule, value, callback) {
                    if (value) {
                        if (!jo.Const.REG_MOBILEPHONE.test(value)) {
                            callback(new Error(msg || '手机号格式错误'));
                            return;
                        }
                    }
                    callback();
                }
                , trigger: trigger || 'blur'
            };
        },
        reg: function (msg, trigger, reg) {
            return {
                validator: function (rule, value, callback) {
                    if (value) {
                        if (!new RegExp(reg).test(value)) {
                            callback(new Error(msg || '格式错误'));
                            return;
                        }
                    }
                    callback();
                }
                , trigger: trigger || 'blur'
            };
        },
        notNaN: function (msg, trigger) {
            return {
                validator: function (rule, value, callback) {
                    if (value) {
                        if (isNaN(value)) {
                            callback(new Error(msg || '非数错误'));
                            return;
                        }
                    }
                    callback();
                }
                , trigger: trigger || 'blur'
            };
        },


        date: function (msg, trigger) {
            return {type: 'date', message: msg || '必须是时间类型', trigger: trigger || 'blur'};
        },
        array: function (msg, trigger) {
            return {type: 'array', message: msg || '必须是数组类型', trigger: trigger || 'blur'};
        },
        object: function (msg, trigger) {
            return {type: 'object', message: msg || '必须是对象类型', trigger: trigger || 'blur'};
        },
        number: function (msg, trigger) {
            return {type: 'number', message: msg || '必须是数字类型', trigger: trigger || 'blur'};
        },
        string: function (msg, trigger) {
            return {type: 'string', message: msg || '必须是字符串类型', trigger: trigger || 'blur'};
        }
    }
})();


// joEl组件
(function () {
    joEl.COMPONENT_MAP = {
        'jo-el-table': {
            // 可以接受的属性
            props: {
                tableRef: {
                    type: String,
                    default: 'tableRef'
                },
                // 数据url
                url: {
                    type: String
                },
                // 列配置
                cols: {
                    type: Array
                },
                // 是否开启分页
                pageEnable: {
                    type: [String, Number, Boolean],
                    default: true
                },
                // 边框
                border: {
                    type: Boolean,
                    default: false
                },
                // 查询参数对象
                searchParam: {
                    type: Object,
                    default: function () {
                        return {};
                    }
                },
                // 渲染表格数据前通过该方法处理数据项
                handleItem: {
                    type: Function,
                },
                // 查询参数处理, 查询前对参数的校准
                handleParam: {
                    type: Function,
                },
                pageSize: {
                    type: Number,
                    default: 10
                },
                pageSizes: {
                    type: Array,
                    default: [10, 20, 50, 100]
                },
                // 首列类型, radio,checkbox,index,none
                firstColumn:{
                    type: String,
                    default: 'none'
                }
            },
            data: function () {
                return {
                    tableData: [],
                    page: {
                        pageNumber: 1,
                        pageSize: this.pageSize,
                        pageSizes: this.pageSizes,
                        total: 0,
                        layout: 'total, sizes, prev, pager, next',   //, jumper
                        hideOnSinglePage: false
                    },
                    // 排序字段
                    sortBy: '',
                    // 排序类型, asc,desc
                    sortType: '',

                    // radio单选框值对象引用
                    radioValue: {
                        value: null
                    }
                };
            },
            computed: {
                // 首列是单选框
                isRadio() {
                    return this.firstColumn === 'radio';
                },
                // 是否分页展示
                showPageBar() {
                    if (this.pageEnable === false
                        || this.pageEnable === 'false'
                        || this.pageEnable === 0) {
                        return false;
                    }
                    return true;
                }
            },
            template: `
            <div class="jo-el-table-bar">
                <div class="jo-el-table-data-bar">
                    <slot :cols="cols" :data="tableData" :radio="radioValue">
                        <el-table :ref="tableRef" :data="tableData" :border="border" header-cell-class-name="jo-el-table-header" 
                            @sort-change="tableSortChange">
                            <slot name="columns" :cols="cols">
                                   <el-table-column v-for="col in cols" :type="col.type" :prop="col.field" :label="col.label"
                                    :width="col.width" :header-align="col.headerAlign" :align="col.align" :formatter="col.formatter">
                                    </el-table-column>
                                    <slot name="oper"></slot>
                            </slot>
                        </el-table>
                    </slot>
                </div>
                <div class="jo-el-table-page-bar" v-if="showPageBar">
                    <slot name="page" :page="page">
                          <el-pagination
                            :currentPage="page.pageNumber"
                            :page-sizes="page.pageSizes"
                            :page-size="page.pageSize"
                            :total="page.total"
                            :layout="page.layout"
                            :background="true"
                            :hide-on-single-page="page.hideOnSinglePage"
                            @size-change="handleSizeChange"
                            @current-change="goPage"
                            class=""
                            small
                            >
                          </el-pagination>
                    </slot>
                </div>
            </div>
            `,
            methods: {
                // 排序{ column, prop, order }
                tableSortChange(sort) {
                    if (sort) {
                        this.sortBy = jo.getDefVal(sort.prop, '');
                        if (sort.order === 'ascending') {
                            // 升序
                            this.sortType = 'asc';
                        } else if (sort.order === 'descending') {
                            // 降序
                            this.sortType = 'desc';
                        } else {
                            this.sortType = '';
                        }
                        // 刷新表格数据
                        this.refresh();
                    }
                },
                // 获取表格ref
                getTableRef() {
                    return joEl.getRef(this, this.tableRef);
                },
                // 获取radio选中项
                getCheckedRadioItem() {
                    if (jo.isValid(this.radioValue.value)) {
                        return this.tableData[this.radioValue.value];
                    }
                    return null;
                },
                // 获取选中项
                getCheckedItemArr() {
                    if (this.isRadio) {
                        var item = this.getCheckedRadioItem();
                        return item ? [item] : [];
                    } else {
                        var table = this.getTableRef();
                        if (!table) {
                            console.error('[jo-el-table] 获取el表格ref为空,tableRef参数=' + this.tableRef);
                            return [];
                        }
                        var arr = table.getSelectionRows();
                        return arr ? arr : [];
                    }
                },
                // 页大小变更
                handleSizeChange(pageSize) {
                    this.searchInvoke({pageNumber: 1, pageSize: pageSize});
                },
                // 去第n页
                goPage(pageNumber) {
                    if (!pageNumber) {
                        pageNumber = 1;
                    }
                    this.searchInvoke({pageNumber: pageNumber});
                },
                // 刷新数据, 也就是重新加载当前页
                refresh() {
                    this.goPage(this.page.pageNumber);
                },
                // 数据查询执行核心方法
                searchInvoke(extParam) {
                    var _this = this;
                    // 构造查询参数, 包括表单参数和分页参数等
                    var param = _this.buildSearchParam(extParam);
                    var url = _this.url;// + jo.getLinkSign(_this.url) + 'pageNumber=' + jo.getDefVal(param.pageNumber, '') + '&pageSize=' + jo.getDefVal(param.pageSize, '')
                    jo.postJsonAjax(url, param).success(function (json) {
                        var list = json.data;
                        jo.forEach(list, function (item, i) {
                            if (typeof _this.handleItem == 'function') {
                                _this.handleItem(item, i);
                            }
                        });
                        _this.tableData = json.data || [];
                        _this.page.pageNumber = json.pageNumber;
                        _this.page.total = json.total;
                    }).error(function (json) {
                        console.warn('[jo-el-table] query error', json);
                    });
                },
                // 构造查询参数
                buildSearchParam(extParam) {
                    // 输入的查询条件
                    var param = {
                        body: this.searchParam ? JSON.parse(JSON.stringify(this.searchParam)) : {}
                    };
                    // 分页参数
                    param.pageNumber = this.page.pageNumber;
                    param.pageSize = this.page.pageSize;
                    // 排序参数
                    if (this.sortBy) {
                        param.body.dbSortBy = this.sortBy;
                    }
                    if (this.sortType) {
                        param.body.dbSortType = this.sortType;
                    }
                    // 指定的扩展参数, 和上面参数重复的, 以扩展参数为准, 可以用来参数校准
                    if (extParam) {
                        param = jo.mergeObject(param, extParam);
                    }
                    // 参数处理钩子
                    if (typeof this.handleParam == 'function') {
                        this.handleParam(param);
                    }
                    return param;
                }
            },
            mounted() {
                this.goPage(1);
                console.info('[jo-el-table] mounted');
            }
        },
        'jo-el-data': {
            props: {
                url: {
                    type: String,
                    default: ''
                },
                // 绑定根属性名
                bindRootName: {
                    type: [String],
                    default: ''
                }
            },
            data: function () {
                return {
                    data: []
                };
            },
            template: `<div class="jo-el-data-bar"><slot :data="data" :url="url"></slot></div>`,
            mounted() {
                var _this = this;
                if (this.url) {
                    jo.postJsonAjax(this.url, {}).success(function (json) {
                        _this.data = json.data;
                        if (_this.bindRootName) {
                            _this.$root[_this.bindRootName] = json.data;
                        }
                    }).error(function (json) {
                        console.warn('[jo-el-data] error, url: ' + _this.url, json);
                    });
                }
                console.info('[jo-el-data] mounted, url: ' + this.url);
            }
        }
    };
})();

// joEl方法库
(function () {
    // 当key不存在时赋值
    joEl.putIfNoValue = function (obj, key, value) {
        if (!jo.isValid(key)) {
            console.info('当前key已存在:' + key)
        } else {
            obj[key] = value;
        }
    };

    /**
     * 构造vue参数, 多个参数合并为一个参数, 优先级为入参顺序
     * @param param 定制参数
     * @param commonParam 合并参数
     * @returns {*}
     */
    joEl.buildVueAppParam = function (param, commonParam) {
        if (arguments.length > 2) {
            for (var i = 1; i < arguments.length; i++) {
                var p = arguments[i];
                param = joEl.buildVueAppParamInvoke(param, p, i);
            }
            return param;
        } else if (commonParam) {
            return joEl.buildVueAppParamInvoke(param, commonParam);
        } else {
            return param;
        }
    };

    // 实际执行vue参数合并函数, idx表示序号参数合并序号, 从1开始
    joEl.buildVueAppParamInvoke = function (param, commonParam, idx) {
        // 初始化方法
        if (!param.methods) {
            param.methods = {};
        }
        idx = jo.getDefVal(idx, 1);
        var preData = 'data__backup';
        var preCommonData = 'common__data__backup';
        // 暂存定制data方法
        param.methods[preData + idx] = param.data;
        param.methods[preCommonData + idx] = commonParam.data;
        // 重写data
        param.data = function () {
            var common = typeof this[preCommonData + idx] == 'function' ? this[preCommonData + idx]() : {};
            var data = typeof this[preData + idx] == 'function' ? this[preData + idx]() : {};
            var result = jo.mergeObject(common, data);
            console.debug('当前data的序号为=%s,公共data=%o,基础data=%o,合并后data=%o', idx, common, data, result);
            return result;
        };

        // 初始化计算变量
        if (!param.computed) {
            param.computed = {};
        }
        if (commonParam.computed) {
            for (var k in commonParam.computed) {
                // 不存在则填充计算变量
                joEl.putIfNoValue(param.computed, k, commonParam.computed[k]);
            }
        }

        // 填充方法
        if (commonParam.methods) {
            for (var k in commonParam.methods) {
                // 不存在则填充方法
                joEl.putIfNoValue(param.methods, k, commonParam.methods[k]);
            }
        }

        // mounted
        if (!param.mounted) {
            param.mounted = commonParam.mounted;
        }

        return param;
    };
})();

// joEl基础app参数
(function () {
    // 公共参数
    joEl.VUE_COMMON = {
        data() {
            return {

            };
        },
        methods: {
            // 获取组件ref
            getRef(refName) {
                return joEl.getRef(this, refName);
            },
            // 刷新页面
            reloadPage() {
                window.location.reload();
            },
        }
    };
    // 视图页参数
    joEl.VUE_COMMON_VIEW = {
        data() {
            return {
                // 查询参数
                searchCondition: {},
                // 更多条件
                moreConditionFlag: false,
                // 表单校验规则
                checkRules: {},
                // 表单详情查询url
                formQueryUrl: '',
                // 新增url
                formInsertUrl: '',
                // 修改url
                formUpdateUrl: '',
                // 删除url
                deleteUrl: '',
                // 新增表单ref
                addFormRef: 'formRef',
                // 编辑表单ref
                editFormRef: 'formRef',

                // 新增表单标题
                addFormTitle: '新增',
                // 新增表单宽度
                addFormWidth: '75%',
                // 编辑表单标题
                editFormTitle: '编辑',
                // 编辑表单宽度
                editFormWidth: '75%',

                // 主键属性名
                primaryKey: 'id',
                // jo表格ref, 无特殊情况不需要改动
                joTableRef: 'joTableRef',
                // el表格ref, 无特殊情况不需要改动
                tableRef: 'tableRef',
                // 表格单选框值
                defaultTableRadio: '',
                // 表单数据
                formData: {},
                // 表单显示开关
                formShow: false,
                // 新增表单标识, 用来区分表单弹层是新增表单(1)还是编辑表单(2)
                formType: 1
            };
        },
        computed: {
            // 新增表单标识
            addFlag() {
                return this.formType == 1;
            },
            // 编辑表单标识
            editFlag() {
                return this.formType == 2;
            },
            // 表单ref
            formRef() {
                if (this.formType === 1) {
                    return this.addFormRef;
                } else if (this.formType === 2) {
                    return this.editFormRef;
                } else {
                    return 'formRef';
                }
            },
            // 表单标题
            formTitle() {
                if (this.formType === 1) {
                    return this.addFormTitle;
                } else if (this.formType === 2) {
                    return this.editFormTitle;
                } else {
                    return '';
                }
            },
            // 表单宽度
            formWidth() {
                if (this.formType === 1) {
                    return this.addFormWidth;
                } else if (this.formType === 2) {
                    return this.editFormWidth;
                } else {
                    return '75%';
                }
            },
        },
        methods: {
            // ************ 回调函数 start ************
            // ************ 回调函数 start ************
            // ************ 回调函数 start ************
            // 新增表单数据初始化前的处理
            handle_form_init_data_add(data) {

            },
            // 编辑表单数据初始化前的处理
            handle_form_init_data_edit(data) {

            },
            // 新增成功后处理, 参数为后端返回结果
            insert_success_after(json) {
                jo.showSuccessMsg('保存成功~');
                // 刷新列表页
                this.list_refresh();
                // 关闭弹层
                this.close_add_form();
            },
            // 新增成功后处理, 参数为后端返回结果
            update_success_after(json) {
                jo.showSuccessMsg('更新成功~');
                // 刷新列表页
                this.list_refresh();
                // 关闭弹层
                this.close_add_form();
            },
            // 删除成功后处理
            delete_success_after(json) {
                jo.showSuccessMsg('删除成功~');
                // 刷新列表页
                this.list_refresh();
            },
            // ************ 回调函数 end ************
            // ************ 回调函数 end ************
            // ************ 回调函数 end ************
            // jo表格ref
            list_jo_table_ref() {
                return this.getRef(this.joTableRef);
            },
            // 表格ref
            // list_table_ref() {
            //     return this.getRef(this.tableRef);
            // },
            // 新增表单ref
            add_form_ref() {
                return this.getRef(this.addFormRef);
            },
            // 编辑表单ref
            edit_form_ref() {
                return this.getRef(this.editFormRef);
            },
            // 获取选中项
            getCheckedItemArr(joTableRef) {
                // 拿到jo表格实例
                var joTable = joTableRef ? this.getRef(joTableRef) : this.list_jo_table_ref();
                if (!joTable) {
                    console.error('[列表页组件] 获取jo表格ref失败.', joTableRef);
                    return [];
                }
                return joTable.getCheckedItemArr();
            },
            // 获取选中项id集合
            getCheckedItemIdArr() {
                var arr = [];
                var _this = this;
                jo.forEach(this.getCheckedItemArr(), function (item) {
                    arr.push(item[_this.primaryKey]);
                });
                return arr;
            },
            // 排序{ column, prop, order }
            list_table_sort(sort) {
                this.list_jo_table_ref().tableSortChange(sort);
            },
            // 列表查询
            list_search() {
                this.list_jo_table_ref().goPage();
            },
            // 列表刷新
            list_refresh() {
                this.list_jo_table_ref().refresh();
            },
            // 打开新增弹层
            open_add_form() {
                this.formShow = true;
                // 重置该表单项，将其值重置为初始值，并移除校验结果
                var ref = this.add_form_ref();
                if (ref) {
                    ref.resetFields();
                }
            },
            // 打开编辑弹层
            open_edit_form() {
                this.formShow = true;
                // 重置该表单项，将其值重置为初始值，并移除校验结果
                var ref = this.edit_form_ref();
                if (ref) {
                    ref.resetFields();
                }
            },
            // 关闭新增弹层
            close_add_form() {
                this.formShow = false;
            },
            // 关闭编辑弹层
            close_edit_form() {
                this.formShow = false;
            },
            // 关闭表单弹层
            close_form() {
                if (this.formType === 1) {
                    this.close_add_form();
                } else if (this.formType === 2) {
                    this.close_edit_form();
                } else {
                    console.error('未知的表单类型(formType):' + this.formType);
                }
            },
            // 初始化新增表单数据
            init_form_data_add() {
                var data = {};
                if (typeof this.handle_form_init_data_add == 'function') {
                    this.handle_form_init_data_add(data);
                }
                this.formData = data;
            },
            // 初始化编辑表单数据
            init_form_data_edit(item) {
                if (!this.formQueryUrl) {
                    console.error('表单详情查询URL无效,请检查配置项[formQueryUrl]');
                    return;
                }
                var _this = this;
                // 先清空, 在查询, 避免错乱
                this.formData = {};
                jo.postJson(this.formQueryUrl, {body: item[this.primaryKey]}).success(function (json) {
                    if (typeof _this.handle_form_init_data_edit == 'function') {
                        _this.handle_form_init_data_edit(json.data);
                    }
                    _this.formData = json.data || {};
                }).error(function (json) {
                    jo.showErrorMsg(json.info || '详情查询失败');
                });
            },

            // 新增
            list_add() {
                this.formType = 1;
                // 打开弹层
                this.open_add_form();
                // 初始化表单数据
                this.init_form_data_add();
            },
            // 编辑
            list_edit(item) {
                this.formType = 2;
                // 打开弹层
                this.open_edit_form();
                // 初始化表单数据
                this.init_form_data_edit(item);
            },
            // 删除
            list_delete(item) {
                var id = typeof item == 'object' ? item[this.primaryKey] : item;
                if (!id) {
                    console.error('[list_delete] 入参待删除项无效');
                    return;
                }
                this.delete_ids(id);
            },
            delete_ids(ids) {
                if (!this.deleteUrl) {
                    console.error('[delete_ids] 删除URL无效,请检查配置项[deleteUrl]');
                    return;
                }
                if (!ids) {
                    console.error('[delete_ids] 入参待删除项无效');
                    return;
                }
                var _this = this;
                jo.confirm('您确定要删除选中项嘛?', function (json) {
                    jo.postJson(_this.deleteUrl, {body: ids}).success(function (json) {
                        _this.delete_success_after(json);
                    }).error(function (json) {
                        jo.showErrorMsg(json.info || '删除失败');
                    });
                });
            },
            // 批量删除
            list_delete_batch() {
                var ids = this.getCheckedItemIdArr().join(',');
                if (!ids) {
                    jo.showTipsMsg('请选择待删除项~');
                    return;
                }
                this.delete_ids(ids);
            },
            // 表单保存
            form_save() {
                if (this.formType === 1) {
                    this.form_insert();
                } else if (this.formType === 2) {
                    this.form_update();
                } else {
                    console.error('未知的表单类型(formType):' + this.formType);
                }
            },
            // 表单新增
            form_insert() {
                var _this = this;
                var param = JSON.parse(JSON.stringify(this.formData));
                this.add_form_ref().validate(function (success, invalidFields) {
                    // invalidFields参数示例: [{field: "code",fieldValue: "",message: "职位编号必填"}]
                    if (success) {
                        jo.postJson(_this.formInsertUrl, {body: param}).success(function (json) {
                            _this.insert_success_after(json);
                        }).error(function (json) {
                            jo.showErrorMsg(json.info || '保存失败');
                        });
                    } else {
                        console.info('[form_insert] 表单校验失败,非法字段:', invalidFields);
                    }
                });
            },
            // 表单修改
            form_update() {
                var _this = this;
                var param = JSON.parse(JSON.stringify(this.formData));
                this.edit_form_ref().validate(function (success, invalidFields) {
                    // invalidFields参数示例: [{field: "code",fieldValue: "",message: "职位编号必填"}]
                    if (success) {
                        jo.postJson(_this.formUpdateUrl, {body: param}).success(function (json) {
                            _this.update_success_after(json);
                        }).error(function (json) {
                            jo.showErrorMsg(json.info || '更新失败');
                        });
                    } else {
                        console.info('[form_update] 表单校验失败,非法字段:', invalidFields);
                    }
                });
            },

        }
    };
})();